﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DirectCanvas;
using DirectCanvas.Brushes;
using DirectCanvas.Effects;
using DirectCanvas.Misc;
using DirectCanvas.Shapes;
using DirectCanvas.Transforms;
using WindowsFormsTest.Demos;
using DirectCanvas.Multimedia;
using DirectCanvas.Scenes;

namespace WPFTestApp.Demos.EffectsDemo
{
    class SuperBlur : Scene
    {
        private readonly Presenter m_presenter;
        private const int SCENE_WIDTH = 825;
        private const int SCENE_HEIGHT = 650;
        private DrawingLayer m_tempLayer;
        private DrawingLayer m_tempLayer2;
        private Brush m_paintingBrush;
        private LinearGradientBrush m_gradientBrush;
        private BlurEffect m_blurEffect;
        private Dictionary<int, PointF> m_positions;

        private MediaPlayer m_player;
        private DrawingLayerBrush m_drawingLayerBrush;
        private DrawingLayerBrush m_drawingLayerBrush2;
        private const string VIDEO_FILENAME = @"C:\Users\Public\Videos\Sample Videos\Wildlife.wmv";

        public SuperBlur(Presenter presenter)
        {
            m_positions = new Dictionary<int, PointF>();
            m_presenter = presenter;
            InitializeResources();
        }

        private void InitializeResources()
        {
            m_tempLayer = m_presenter.Factory.CreateDrawingLayer(SCENE_WIDTH, SCENE_HEIGHT);
            m_tempLayer2 = m_presenter.Factory.CreateDrawingLayer(SCENE_WIDTH, SCENE_HEIGHT);
            m_drawingLayerBrush = m_presenter.Factory.CreateDrawingLayerBrush(m_tempLayer);
            m_drawingLayerBrush2 = m_presenter.Factory.CreateDrawingLayerBrush(m_tempLayer2);
            m_blurEffect = new BlurEffect(m_presenter.Factory);

            GradientStop[] stops = new GradientStop[3];

            stops[0].Position = 0;
            stops[0].Color = new Color4(1f, 1, 0, 0);

            stops[1].Position = 0.5f;
            stops[1].Color = new Color4(1f, 0, 1, 0);

            stops[2].Position = 1f;
            stops[2].Color = new Color4(.1f, 0, 0, 1);

            m_gradientBrush = m_presenter.Factory.CreateLinearGradientBrush(stops, ExtendMode.Clamp, new PointF(0, 0), new PointF(SCENE_WIDTH, 0));
            m_gradientBrush.Transform = new RotateTransform();

            //m_paintingBrush = m_presenter.DirectCanvas.CreateRadialGradientBrush(stops,
            //                                                                    ExtendMode.Clamp,
            //                                                                    new PointF(500, 500),
            //                                                                    new PointF(0, 0),
            //                                                                    new SizeF(500, 500));

            InitMediaPlayer();
        }

        private void InitMediaPlayer()
        {
            m_player = m_presenter.Factory.CreateMediaPlayer();
            m_player.Open(VIDEO_FILENAME);
            
            var videoBrush = m_presenter.Factory.CreateVideoBrush(m_player);
            videoBrush.HorizontalExtendMode = ExtendMode.Wrap;
            videoBrush.VerticalExtendMode = ExtendMode.Wrap;
            m_paintingBrush = videoBrush;
        }

        public override void ActivateScene()
        {
            m_player.Play();
        }

        public override void DeactivateScene()
        {
            m_player.Pause();
        }

        public override void Render()
        {
            var positionsCopy = new List<PointF>(m_positions.Values);
            
            var rect = new RectangleF(0, 0, SCENE_WIDTH, SCENE_HEIGHT);
          
            m_drawingLayerBrush.Transform = new RotateTransform() { Angle = .2f, CenterX = SCENE_WIDTH / 2, CenterY = SCENE_HEIGHT / 2 };
            
            m_tempLayer2.BeginDraw();

            m_tempLayer2.FillRectangle(m_drawingLayerBrush, rect);

            m_tempLayer2.EndDraw();

          

            m_tempLayer.BeginDraw();
            m_tempLayer.FillRectangle(m_drawingLayerBrush2, rect);

            m_paintingBrush.Alignment = BrushAlignment.DrawingLayerRelative;

            foreach (var point in positionsCopy)
            {
                m_tempLayer.FillRoundedRectangle(m_paintingBrush, new RoundedRectangleF(point.X - 25, point.Y - 25, 50, 50, 20, 20));
            }

            m_tempLayer.EndDraw();


            m_blurEffect.Sigma = 2f;

            float multiplier = 0.90f;
            m_blurEffect.Tint = new Color4(multiplier, multiplier, multiplier, multiplier);
            m_blurEffect.Direction = BlurDirection.Horizontal;
            m_blurEffect.SampleSize = new SizeF(SCENE_WIDTH / 2, SCENE_HEIGHT / 2);
            
            m_tempLayer.ApplyEffect(m_blurEffect, m_tempLayer2);

            m_blurEffect.Direction = BlurDirection.Vertical;
            m_blurEffect.SampleSize = new SizeF(SCENE_WIDTH / 2, SCENE_HEIGHT / 2);
            m_tempLayer2.ApplyEffect(m_blurEffect, m_tempLayer);

            m_tempLayer.BeginDraw();
            m_paintingBrush.Alignment = BrushAlignment.DrawingLayerRelative;

            foreach (var point in positionsCopy)
            {
                m_tempLayer.FillRoundedRectangle(m_paintingBrush, new RoundedRectangleF(point.X - 25, point.Y - 25, 50, 50, 20, 20));
            }
            m_tempLayer.EndDraw();

            m_presenter.Clear();
            m_presenter.BeginDraw();
            m_presenter.DrawLayer(m_tempLayer);
            m_presenter.EndDraw();
        }

        public override void SetInputState(int inputId, InputStatus status, PointF position)
        {
            if (status == InputStatus.Down)
            {
                if (!m_positions.ContainsKey(inputId))
                {
                    m_positions.Add(inputId, position);
                }
                else
                {
                    m_positions[inputId] = position;
                }
            }
            else if (m_positions.ContainsKey(inputId))
            {
                m_positions.Remove(inputId);
            }
        }
    }
}
